package com.hqd.ch03.v51.boot.context.properties;

import com.hqd.ch03.v51.beans.support.PropertySourcesPlaceholderConfigurer;
import com.hqd.ch03.v51.context.ApplicationContext;
import com.hqd.ch03.v51.core.env.ConfigurableEnvironment;
import com.hqd.ch03.v51.core.env.Environment;
import com.hqd.ch03.v51.core.env.MutablePropertySources;
import com.hqd.ch03.v51.core.env.PropertySources;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.Map;

class PropertySourcesDeducer {

    private static final Log logger = LogFactory.getLog(PropertySourcesDeducer.class);

    private final ApplicationContext applicationContext;

    PropertySourcesDeducer(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    PropertySources getPropertySources() {
        PropertySourcesPlaceholderConfigurer configurer = getSinglePropertySourcesPlaceholderConfigurer();
        if (configurer != null) {
            return configurer.getAppliedPropertySources();
        }
        MutablePropertySources sources = extractEnvironmentPropertySources();
        return sources;
    }

    private PropertySourcesPlaceholderConfigurer getSinglePropertySourcesPlaceholderConfigurer() {
        // Take care not to cause early instantiation of all FactoryBeans
        Map<String, PropertySourcesPlaceholderConfigurer> beans = this.applicationContext
                .getBeansOfType(PropertySourcesPlaceholderConfigurer.class);
        if (beans.size() == 1) {
            return beans.values().iterator().next();
        }
        if (beans.size() > 1 && logger.isWarnEnabled()) {
            logger.warn("Multiple PropertySourcesPlaceholderConfigurer beans registered " + beans.keySet()
                    + ", falling back to Environment");
        }
        return null;
    }

    private MutablePropertySources extractEnvironmentPropertySources() {
        Environment environment = this.applicationContext.getEnvironment();
        if (environment instanceof ConfigurableEnvironment) {
            return ((ConfigurableEnvironment) environment).getPropertySources();
        }
        return null;
    }

}

